#ifndef DEVICEMANAGER_H
#define DEVICEMANAGER_H

/**
 * @copyright Copyright (c) 2025 
 * CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author zhouyan
 * @brief 设备管理头文件
*/
#include "sys_inc.h"
#include "phylink.h"

typedef std::vector<ComSettings *> UseUart;

typedef struct WhiteListData
{
    int32_t     UartIndex;
    std::string Protocol;  
    uint16_t DevNum;        
    uint16_t ReadFunCode;
    uint16_t WriteFunCode;
    uint16_t RegStartAddr;
    uint16_t RegNum;
    std::string SerialNumber;
    uint16_t WhiteIdx;
} WhiteDev_;

typedef struct WriteDevData
{
    uint8_t  Addr;
    uint16_t ReadFunCode;
    uint16_t WriteFunCode;
    uint16_t RegStartAddr;
    uint16_t RegNum;
    uint8_t  SendBuf[256];
} WriteDev_;

class IPhyLink;
class IDevice;
class Gather;
class CLog;
typedef struct cJSON cJSON;

class DeviceManager
{
    friend void downLinkTest(void);
    typedef IDevice *(*PFN_CreateDevice)(const char *, uint16_t , uint16_t , IPhyLink *);
    typedef void (*PFN_ReleaseDevice)(IDevice *);
    typedef const char * (*PFN_GetVersion)(void);
    typedef bool (*PFN_SetLogInst)(CLog *log, CLog *frame);
    typedef void (*PFN_Start)(void);
    typedef void (*PFN_SetHandler)(void* handler);
    struct dl_info {
        void * dp;
        PFN_CreateDevice createDevice;
        PFN_ReleaseDevice releaseDevice;
        PFN_GetVersion getVersion;
        PFN_SetLogInst setLogInst;
        PFN_Start start;
        PFN_SetHandler setHandler;
    };
    typedef std::map<std::string, dl_info> dl_infos;

public:
    typedef std::list<IDevice *> IDevices;
    typedef std::map<std::string, Gather *> Gathers;
    typedef std::map<uint16_t, IDevices *> Bays;

    ~DeviceManager();

    static DeviceManager * mgr(void);

    IDevice *device(uint16_t bay_id, uint16_t dev_id, int dev_type = 0);
    IDevices *devices(uint16_t bay_id);
    const std::vector<uint16_t> & bayIds(void) const {return ids_;}
    uint16_t maxDevId(uint16_t bay_id, int dev_type = 0);
    int loadDevice();
    void setDebugDevice(int com_index, int dev_index);
    void ShowDeviceList(int com_index);

    void startGather(void);
    void stopGather(void);

    void getModelNames(std::list<std::string> &model_names);
    void getDevices(const std::string &model_name, IDevices &devs);

protected:
    DeviceManager();

private:
    Gather *findGather(const char *link_name);
    bool loadBay(cJSON *root, int type = 0);
    bool loadModelFile(cJSON *root,
                       const char    *model_file,
                       int32_t       uart_index,
                       uint16_t      bay_id,
                       IDevices      *devs,
                       int           type = 0,
                       uint16_t      dev_id_offset = 0);


    IDevice *genDevice(
                cJSON                *root,
                cJSON                *root_model,
                const char           *model_file,
                int32_t              uart_index,
                uint16_t             bay_id,
                int                  type,
                uint16_t             dev_id_offset,
                const std::string    &protocol);

    dl_info loadDll(const std::string &dll);

private:
    bool parseDevInfo(cJSON *root, uint16_t bay_id, uint16_t &dev_id, uint64_t &dev_addr, uint8_t &index, const std::string& protocol);

private:
    Bays bays_;
    std::vector<uint16_t> ids_;
    std::map<std::string, Gather *> gathers_;

    dl_infos         dl_infos_;
};

void downLinkTest(void);

#endif // DEVICEMANAGER_H
